using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using id3;

namespace PodInvaders
{
	public partial class MainForm : Form
	{
		private List<IPod> _ipods = new List<IPod>();
		private string _copyDirectory = null;
		private bool _search = false;

		private delegate void AddToListView(MP3 mp3);
		private delegate void SetListViewLayout(bool On);
        private delegate void SearchCompleted(string[] files);

		private enum Persistence
		{
			Search
		}

		private enum TrackListSubItems
		{
			Album,
			Artist,
			Path,
			Title,
			TrackNumber
		}

		public MainForm()
		{
			InitializeComponent();
			InputPersistence.LoadUserInput(cmbSearch, Persistence.Search.ToString());
			FindIpods();
		}

		private void FindIpods()
		{
#if DEBUG
            _ipods = new List<IPod>();
            _ipods.Add(new IPod("My iPod", @"C:\Documents and Settings\ayeletr\My Documents\"));
#else
            Invader invader = new Invader();
			_ipods = invader.FindIpods();
#endif

            if (_ipods.Count == 0)
			{
                cmbSearch.Text = Properties.Resources.NoIpodsFound;
				return;
			}

			foreach (IPod pod in _ipods)
			{
				AddIpod(pod);
			}
		}

		private void StartSearch()
		{
			if(_search)
			{
				btnSearch.Text = Properties.Resources.Search;
				_search = false;
				return;
			}

            string path;

            if (cmbSearch.SelectedItem != null && cmbSearch.SelectedItem.GetType() == typeof(IPod))
            {
                path = ((IPod)cmbSearch.SelectedItem).MusicRoot;
            }
            else
            {
                path = cmbSearch.Text;
            }

			if(!Directory.Exists(path))
			{
				MessageBox.Show("Can't search: " + cmbSearch.Text, Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				cmbSearch.Focus();
				return;
			}

			InputPersistence.SaveUserInput(cmbSearch, Persistence.Search.ToString());
			lvTracks.Items.Clear();
			btnSearch.Text = Properties.Resources.CancelSearch;
			_search = true;
			Thread search = new Thread(Search);
			search.Start(path);
		}

		private void Search(object RootPath)
		{
			string[] files = Directory.GetFiles((string)RootPath, "*.mp3", SearchOption.AllDirectories);
			MP3 mp3;

			if (InvokeRequired)
				Invoke(new SetListViewLayout(setListViewLayout), false);
			else
				setListViewLayout(false);

			for (int i = 0; i < files.Length && _search; i++)
			{
				mp3 = new MP3(files[i], "");
				FileCommands.readMP3Tag(ref mp3);

				if (InvokeRequired)
					Invoke(new AddToListView(addToListView), mp3);
				else
					addToListView(mp3);
			}

			if (InvokeRequired)
				Invoke(new SetListViewLayout(setListViewLayout), true);
			else
				setListViewLayout(true);

            if (InvokeRequired)
                Invoke(new SearchCompleted(searchCompleted), files);
            else
                searchCompleted(files);
		}

		private void setListViewLayout(bool On)
		{
			if (On)
				lvTracks.ResumeLayout();
			else
				lvTracks.SuspendLayout();
		}

		private void addToListView(MP3 mp3)
		{
			ListViewItem.ListViewSubItem[] subItems = new ListViewItem.ListViewSubItem[5]
			{
				GetSubItem(TrackListSubItems.Title, mp3.Title),
				GetSubItem(TrackListSubItems.Artist, mp3.Artist),
				GetSubItem(TrackListSubItems.Album, mp3.Album),
				GetSubItem(TrackListSubItems.TrackNumber, mp3.TrackNumber.ToString()),
				GetSubItem(TrackListSubItems.Path, mp3.FilePath)
			};
			ListViewItem lvi = new ListViewItem(subItems, 0);
			lvi.BackColor = (lvTracks.Items.Count % 2 == 0) ? Color.White : Color.LightSkyBlue;

			lvTracks.Items.Insert(0, lvi);
		}

        private void searchCompleted(string[] files)
        {
            btnSearch.Text = Properties.Resources.Search;
        }

		private ListViewItem.ListViewSubItem GetSubItem(TrackListSubItems Key, string Text)
		{
			ListViewItem.ListViewSubItem lbsi = new ListViewItem.ListViewSubItem();
			lbsi.Text = Text;
			lbsi.Name = Key.ToString();

			return lbsi;
		}

		private void Sort(int[] Columns)
		{
			lvTracks.ListViewItemSorter = new ListViewItemSorter(Columns);
		}

		private void AddIpod(IPod ipod)
		{
			cmbSearch.Items.Insert(0, ipod);
			cmbSearch.SelectedIndex = 0;
		}

		private void DoCopy(object CopyInfo)
		{
			CopyInfo ci = (CopyInfo)CopyInfo;

			foreach (string path in ci.Files)
			{
				FileInfo f = new FileInfo(path);
				f.CopyTo(Path.Combine(ci.TargetDirectory, f.Name), true);
			}
		}

		private void Copy(bool PromptForDirectory)
		{
			if(_copyDirectory == null || PromptForDirectory)
			{
				DialogResult d = folderBrowser.ShowDialog();

				if(d == DialogResult.Cancel)
					return;

				_copyDirectory = folderBrowser.SelectedPath;
			}

			CopyInfo ci = new CopyInfo(SelectedPaths, _copyDirectory);
			Thread copy = new Thread(DoCopy);
			copy.Start(ci);
		}

		private string SelectedPath
		{
			get
			{
				if(lvTracks.SelectedItems.Count == 0)
					return null;
				return lvTracks.SelectedItems[0].SubItems[TrackListSubItems.Path.ToString()].Text;
			}
		}

		private string[] SelectedPaths
		{
			get
			{
				if(lvTracks.SelectedItems.Count == 0)
					return null;

				string[] paths = new string[lvTracks.SelectedItems.Count];

				for(int i = 0; i < lvTracks.SelectedItems.Count; i++)
				{
					paths[i] = lvTracks.SelectedItems[i].SubItems[TrackListSubItems.Path.ToString()].Text;
				}
				return paths;
			}
		}

		private void btnSearch_Click(object sender, EventArgs e)
		{
			StartSearch();
		}

		private void lvTracks_ColumnClick(object sender, ColumnClickEventArgs e)
		{
			int[] columns;

			switch(e.Column)
			{
				// Artist
				case 1:

					columns = new int[]{1, 2, 3};
					break;

				// Album
				case 2:

					columns = new int[]{2, 3};
					break;

				default:

					columns = new int[]{e.Column};
					break;
			}

			Sort(columns);
		}

		private void tsmiCopy_Click(object sender , EventArgs e)
		{
			Copy(false);
		}

		private void tsmiCopyTo_Click(object sender , EventArgs e)
		{
			Copy(true);
		}

		private void tsmiShowInExplorer_Click(object sender , EventArgs e)
		{
			Process.Start("explorer.exe", string.Format("/select,\"{0}\"", SelectedPath));
		}

		private void lvContextMenu_Opening(object sender , System.ComponentModel.CancelEventArgs e)
		{
			tsmiShowInExplorer.Visible = lvTracks.SelectedItems.Count == 1;
			tsmiCopy.Visible = tsmiCopyTo.Visible = lvTracks.SelectedItems.Count > 0;
		}
	}
}